﻿using DotNetCommon;
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using System.Linq;
using System.Collections.Generic;
using DotNetCommon.Extensions;

namespace ProjectGenerator
{
    class Program
    {
        private static IConfiguration configuration = null;
        [STAThread]
        static void Main(string[] args)
        {
            var builder = new ConfigurationBuilder();
            var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AppSettings.json");
            builder.AddJsonFile(filePath);
            configuration = builder.Build();
            var appsettings = configuration.Get<AppSettings>();
            if (appsettings.Templates.IsNullOrEmpty())
            {
                Log("必须在AppSettings.json的\"Templates\"节点下配置模板列表!");
                return;
            }
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            Log($"可选的项目模板列表:");
            for (int i = 0; i < appsettings.Templates.Count; i++)
            {
                Log($"    {i + 1}. {appsettings.Templates[i].Name}");
            }
            Console.Write($"请选择(默认: 1):");
            var type = Console.ReadLine();
            if (string.IsNullOrWhiteSpace(type)) type = "1";
            int index = type.ToWithDefault<int>(0);
            if (index == 0 || index > appsettings.Templates.Count)
            {
                Log("输入不合法！");
                return;
            }
            index--;
            var template = appsettings.Templates[index];
            var defaultName = $"{template.SlnName}";
            Console.Write($"输入解决方案名称(默认: {defaultName}):");
            var name = Console.ReadLine();
            if (string.IsNullOrWhiteSpace(name)) name = defaultName;
            var srcZip = template.Zip;
            var zipName = Path.GetFileNameWithoutExtension(srcZip);
            var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, srcZip);
            var srcDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "templates", zipName);
            if (Directory.Exists(srcDir)) Directory.Delete(srcDir, true);
            ZipHelper.UnZipFile(path, srcDir);
            //获取可用的目录  
            var defaultDir = GetDirectoryAwailable(name);
            var buildDir = GetDirectoryAwailable(name);
            while (true)
            {
                Console.Write($"指定输出目录,可以使用如下默认的: \r\n\t{defaultDir}\r\n或者是手动输入(直接回车表示默认):");
                var inputDir = Console.ReadLine();
                if (string.IsNullOrWhiteSpace(inputDir))
                {
                    buildDir = defaultDir;
                    Directory.CreateDirectory(buildDir);
                    break;
                }
                else
                {
                    inputDir = Path.GetFullPath(inputDir);
                    if (Directory.Exists(inputDir) && (Directory.GetFiles(inputDir).Length > 0 || Directory.GetDirectories(inputDir).Length > 0))
                    {
                        Console.Write($"当前目录不为空,是否继续(1 or 0)?");
                        var str = Console.ReadLine();
                        if (str != "1")
                        {
                            continue;
                        }
                    }
                    if (!Directory.Exists(inputDir))
                    {
                        Directory.CreateDirectory(inputDir);
                    }
                    buildDir = inputDir;
                    break;
                }
            }
            //递归替换
            ReplaceRecursive(name, srcDir, buildDir);
            //
            Log($"解决方案已生成:{buildDir}");
            Process.Start("Explorer.exe", buildDir);
            //提示退出
            Log("按任意键退出...");
            Console.Read();
        }

        private static string GetDirectoryAwailable(string name)
        {
            var buildDir = "";
            var index = 0;
            buildDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "generate", $"{name}");
            while (Directory.Exists(buildDir))
            {
                index++;
                buildDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "generate", $"{name}.{index}");
            }
            Directory.CreateDirectory(buildDir);
            return buildDir;
        }

        private static void ReplaceRecursive(string name, string src, string buildDir)
        {
            var files = Directory.GetFiles(src);
            foreach (var file in files)
            {
                if (file.EndsWith(".sln"))
                {
                    var buildPath = Path.Combine(buildDir, Path.GetFileName(file).Replace("ProjectTemplate.", $"{name}."));
                    var text = File.ReadAllText(file, Encoding.GetEncoding("GB2312")).Replace("ProjectTemplate.", $"{name}.");
                    File.WriteAllText(buildPath, text, Encoding.UTF8);
                }
                else if (file.EndsWith(".cs"))
                {
                    var buildPath = Path.Combine(buildDir, Path.GetFileName(file));
                    var text = File.ReadAllText(file, Encoding.GetEncoding("GB2312")).Replace("ProjectTemplate.", $"{name}.");
                    File.WriteAllText(buildPath, text, Encoding.UTF8);
                }
                else if (file.EndsWith(".csproj"))
                {
                    var buildPath = Path.Combine(buildDir, Path.GetFileName(file).Replace("ProjectTemplate.", $"{name}."));
                    var text = File.ReadAllText(file, Encoding.GetEncoding("GB2312")).Replace("\\ProjectTemplate.", $"\\{name}.");
                    File.WriteAllText(buildPath, text, Encoding.UTF8);
                }
                else if (file.EndsWith(".json"))
                {
                    var buildPath = Path.Combine(buildDir, Path.GetFileName(file));
                    var text = File.ReadAllText(file, Encoding.UTF8).Replace("ProjectTemplate.", $"{name}.");
                    File.WriteAllText(buildPath, text, Encoding.UTF8);
                }
                else if (file.EndsWith(".config"))
                {
                    var buildPath = Path.Combine(buildDir, Path.GetFileName(file));
                    var text = File.ReadAllText(file, Encoding.UTF8).Replace("ProjectTemplate.", $"{name}.");
                    File.WriteAllText(buildPath, text, Encoding.UTF8);
                }
                else
                {
                    var buildPath = Path.Combine(buildDir, Path.GetFileName(file));
                    File.Copy(file, buildPath, true);
                }
            }
            var dirs = Directory.GetDirectories(src);
            foreach (var dir in dirs)
            {
                var dirname = Path.GetFileName(dir).Replace("ProjectTemplate.", $"{name}.");
                var buildDir2 = Path.Combine(buildDir, dirname);

                Directory.CreateDirectory(buildDir2);
                ReplaceRecursive(name, dir, buildDir2);
            }
        }

        private static void Log(string message)
        {
            Console.WriteLine(message);
        }
    }

    class AppSettings
    {
        public List<Template> Templates { get; set; }
    }

    class Template
    {
        public string Name { get; set; }
        public string Encoding { get; set; }
        public string Zip { get; set; }
        public string Description { get; set; }
        public string SlnName { get; set; }
    }
}
